package com.cykj.annoation;

import cn.dev33.satoken.stp.StpUtil;
import com.cykj.entity.LogDO;
import com.cykj.mapper.LogMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Optional;

/**
 * @Program: Mooc-Admin
 * @Package: com.cykj.annoation
 * @Author: 张俊杰
 * @Create: 2025-07-15 15:46
 * @Description: TODO
 * @Vision: 1.0
 **/
@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class LogAspect {

    @Autowired
    private LogMapper logMapper; // 假设你是 JPA，如果是 Mapper，改为 mapper 调用即可

    @Pointcut("@annotation(com.cykj.annoation.Log)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log logAnnotation = method.getAnnotation(Log.class);
        String module = logAnnotation.model();
        String action = logAnnotation.value();

        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        String params = Arrays.toString(joinPoint.getArgs());

        Object result = null;
        boolean success = true;

        try {
            result = joinPoint.proceed();
            return result;
        } catch (Throwable ex) {
            success = false;
            throw ex; // 继续抛出，让业务层处理
        } finally {
            long end = System.currentTimeMillis();

            LogDO logDO = new LogDO();
            logDO.setModule(module);  // 可从注解中传递 module
            logDO.setAction(action);
            logDO.setIp(getClientIp());
            logDO.setMethod(methodName);
            logDO.setOperatorName(getOperatorName());
            logDO.setParams(params);
            logDO.setResult(result != null ? result.toString() : "null");
            logDO.setSuccess(success);
            logDO.setOperateTime(LocalDateTime.now());

            logMapper.insertLog(logDO); // 插入数据库
        }
    }

    private String getClientIp() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return Optional.ofNullable(request.getHeader("X-Forwarded-For"))
                .orElse(request.getRemoteAddr());
    }

    private String getOperatorName() {
        return StpUtil.isLogin()
            ? (String) StpUtil.getSession().get("username")
            : "未登录";
    }

}
